home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 19
/
CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso
/
CUCD
/
Programming
/
LEDA
/
prog
/
graphics
/
delaunay.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-05
|
6KB
|
362 lines
#include <LEDA/impl/delaunay_tree.h>
#include <LEDA/plane.h>
#include <LEDA/window.h>
window* Wp;
const double R = 1000; // "length of inifinite rays"
int ymax;
int segment_to_points(segment s, list<point>& out, double dist)
{
int n = int(s.length()/dist) + 2;
double dx = (s.xcoord2() - s.xcoord1())/n;
double dy = (s.ycoord2() - s.ycoord1())/n;
double x = s.xcoord1();
double y = s.ycoord1();
out.append(s.start());
for(int i = 0; i<n; i++)
{ x += dx + double(random(-100,100))/1000000;
y += dy + double(random(-100,100))/1000000;
out.append(point(x,y));
}
return n;
}
int circle_to_points(circle C, list<point>& out, double dist)
{
point c = C.center();
double r = C.radius();
int n = int(6.283 * r/dist);
double alpha = 0;
double d = 6.283/n;
for(int i = 0; i<n; i++)
{ out.append(c.translate(alpha,r+double(random(-100,100))/1000000));
alpha += d;
}
out.permute();
return n;
}
void draw_vor_site(double x, double y)
{ Wp->draw_point(x,y,blue); }
void draw_vor_seg(double x1, double y1, double x2, double y2,double,double)
{ Wp->draw_segment(x1,y1,x2,y2,red); }
void draw_triang_seg(double x1, double y1, double x2, double y2)
{ Wp->draw_segment(x1,y1,x2,y2,green);
}
void infi_pt(double x1, double y1, double x2, double y2, double *x, double* y)
/* retourne le point a l'infini dans la direction x2 y2 depuis x1 y1*/
{
vector v(x2,y2);
v = v.norm();
*x = x1 + R * v[0];
*y = y1 + R * v[1];
}
DELAUNAY_TREE<int> DT;
int display = 0;
DT_item near_it = nil;
bool vor = false;
bool triang = false;
list<segment> CH;
void insert_point(point p)
{ Wp->draw_point(p,blue);
DT.insert(p,0);
}
void insert_segment(segment s)
{ list<point> pl;
segment_to_points(s,pl,10/Wp->scale());
point p;
forall(p,pl) insert_point(p);
}
void insert_circle(circle c)
{ list<point> pl;
circle_to_points(c,pl,10/Wp->scale());
point p;
forall(p,pl) insert_point(p);
}
void draw()
{ segment s;
switch(display) {
case 0: DT.trace_voronoi_edges(draw_vor_seg,infi_pt);
break;
case 1: DT.trace_triang_edges(draw_triang_seg);
break;
case 2: { list<DT_item> L;
DT.convex_hull(L);
list_item it;
Wp->set_line_width(2);
forall_items(it,L)
{ point p = DT.key(L[it]);
point q = DT.key(L[L.cyclic_succ(it)]);
Wp->draw_segment(p,q,violet);
}
Wp->set_line_width(1);
break;
}
}
}
void redraw()
{ DT.trace_voronoi_sites(draw_vor_site);
draw();
}
void interactive(window& W)
{
W.set_redraw(redraw);
W.set_mode(xor_mode);
W.set_node_width(4);
panel P("DYNAMIC VORONOI DIAGRAMS");
P.text_item(" based on Delaunay Trees ");
P.text_item(" by Olivier Devillers ");
P.text_item(" ");
int but = -1;
int N = 500;
int grid_width = 0;
P.choice_item("show",display,"voronoi","triang","c-hull");
P.int_item("grid", grid_width,0,40);
P.int_item("rand sites ",N);
P.button("random");
P.button("point");
P.button("segment");
P.button("circle");
P.button("delete");
P.button("neighbor");
P.button("clear");
P.button("quit");
for(;;)
{
draw(); // draw picture
but=P.open(0,0);
if (but == 7) break;
draw(); // delete previous drawing
W.set_grid_mode(grid_width);
switch (but) {
case 0: { for(int i=0; i<N; i++)
insert_point(point(random(10,500),random(10,ymax)));
break;
}
case 1: { point p;
while (W >> p) insert_point(p);
break;
}
case 2: { segment s;
while (W >> s) insert_segment(s);
break;
}
case 3: { circle c;
while (W >> c) insert_circle(c);
break;
}
case 4: { point p;
while (W >> p)
{ DT_item it = DT.neighbor(p);
if (it)
{ W.draw_point(DT.key(it),blue);
DT.del_item(it);
}
}
break;
}
case 5: { point p;
while (W >> p)
{ if (near_it) W.draw_filled_node(DT.key(near_it));
near_it = DT.neighbor(p);
if (near_it) W.draw_filled_node(DT.key(near_it));
}
if (near_it) W.draw_filled_node(DT.key(near_it));
near_it = nil;
break;
}
case 6: { DT.clear();
W.clear();
CH.clear();
near_it = nil;
}
} // switch
} // for(;;)
}
void demo(int N, int sec)
{ int i;
while(Wp->get_button() == 0)
{
DT.clear();
Wp->clear();
Wp->message(string("%d sites",N));
Wp->flush();
for (i=0; i<N ; i++)
{ point p(random(10,500),random(10,ymax));
DT.insert(p,i);
*Wp << p;
}
//DT.trace_voronoi_sites( draw_vor_site);
DT.trace_voronoi_edges( draw_vor_seg,infi_pt);
Wp->flush();
wait(sec);
Wp->clear();
DT.trace_triang_edges( draw_triang_seg);
Wp->flush();
wait(sec);
}
}
/*
#include <LEDA/stream.h>
*/
main(int argc, char** argv)
{
/*
#define SCREEN_WIDTH 1152
#define SCREEN_HEIGHT 900
string_istream arguments(argc-1,argv+1);
int N=0;
float f1=1;
float f2=1;
float w,h,xpos,ypos;
int position=0;
arguments >> f1;
arguments >> f2;
if (f1 == 0 && f2 == 0)
{ f1 = 0.75;
f2 = 0.95;
}
else
if (f2 == 0)
f2 = f1;
else
{ arguments >> position;
arguments >> N;
}
w = SCREEN_WIDTH*f1;
h = SCREEN_HEIGHT*f2;
switch(position) {
case 0: xpos = SCREEN_WIDTH - w; // upper right corner
ypos = 0;
break;
case 1: xpos = 0; // upper left corner
ypos = 0;
break;
case 2: xpos = 0;
ypos = SCREEN_HEIGHT - h; // lower left corner
break;
case 3: xpos = SCREEN_WIDTH - w; // lower right corner
ypos = SCREEN_HEIGHT - h;
break;
}
window W(w,h,xpos,ypos);
*/
int N = (argc > 1) ? atoi(argv[1]) : 0;
window W;
W.set_flush(false);
W.init(0,512,0);
Wp = &W;
ymax = int(W.ymax()-10);
if (N==0)
interactive(W);
else
demo(N,2);
return 0;
}